#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sqlite3.h>
#include <signal.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "common.h"

int main(int argc, char *argv[])
{
	int listenfd, connectfd;
	struct sockaddr_in server_addr;
	struct sockaddr_in client_addr;
	socklen_t addrlen = sizeof(struct sockaddr_in);

	pid_t pid;
	sqlite3 *db;
	
	if (argc < 3)
	{
		printf("Usage : %s <ip> <port>\n", argv[0]);
		exit(-1);
	}
	
	if (create_open_database(DATABASE, &db) != SQLITE_OK)
	{
		err_log("error");
		exit(-1);
	}

	if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		err_log("fail to socket");
		exit(-1);
	}

	bzero(&server_addr, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = inet_addr(argv[1]);
	server_addr.sin_port = htons(atoi(argv[2]));

	if (bind(listenfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
	{
		err_log("fail to bind");
		exit(-1);
	}
	if (listen(listenfd, 5) < 0)
	{
		err_log("fail to listen");
		exit(-1);
	}

	signal(SIGCHLD, SIG_IGN);// 避免僵尸进程
	while ( 1 )
	{
		if((connectfd = accept(listenfd, (struct sockaddr *)&client_addr, &addrlen))  < 0)
		{
			err_log("fail to accept");
			exit(-1);
		}
		if ((pid = fork()) < 0)
		{
			err_log("fail to fork");
			exit(-1);
		}
		if (pid == 0)
		{
		    close(listenfd);
			do_client(connectfd, db);
		}
		close(connectfd);
	}
	return 0;
}

/*****************  创建数据库  ****************************/
int create_open_database(const char* db_name, sqlite3** db) 
{
	char *errmsg;
	char sql[256] = {0};

	if(sqlite3_open(db_name, db) != SQLITE_OK) {    
		err_log(sqlite3_errmsg(*db));
		return -1;
	} else {
		printf("create or open %s success\n", db_name);
	}

	if(strncmp(db_name, DATABASE, 9) == 0) {
		memset(sql, 0, sizeof(sql));
		sprintf(sql, "create table if not exists %s(root integer, name char, password char,addr char,age integer,level integer,no integer primary key,phone char,salary double);", db_name)
;
		if(sqlite3_exec(*db, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
			err_log(sqlite3_errmsg(*db));
			return -1;
		}
	} 
	
	return 0;
}

/*****************  管理员注册  ****************************/

void do_register(int connectfd, USER_INFO *user_info, sqlite3 *db)
{
	char sqlstr[256] = {0};
	char *errmsg;

	sprintf(sqlstr, "insert into user_info(name, password, root) values('%s', '%s', '%d')", user_info->name, user_info->password, user_info->root);
	
	if(sqlite3_exec(db, sqlstr, NULL, NULL, &errmsg) != SQLITE_OK)
	{
		sprintf(user_info->data, "user %s already exist!!!", user_info->name);
	}
	else
	{
		strncpy(user_info->data, "OK", 3);
	}

	send(connectfd, user_info, sizeof(USER_INFO), 0);

	return;
}

int login_callback(void *arg, int f_num, char **f_value, char **f_name)
{
	int connectfd;
	USER_INFO user_info;
	connectfd = *(int *)arg;
	sscanf(f_value[0], "%d", &user_info.root);  // root
	printf("userinfo.root = %d\n", user_info.root);

	strncpy(user_info.data, "OK", 3);
	if(send(connectfd, &user_info, sizeof(USER_INFO), 0) < 0) {
		err_log("Failed to send");
	}

	return 0;
}

void do_login(int connectfd, USER_INFO *user_info, sqlite3 *db)
{
	char sqlstr[256] = {0};
	char *errmsg, **result;
	int nrow, ncolumn;

	sprintf(sqlstr, "select * from user_info where name = '%s' and password = '%s'", user_info->name, user_info->password);
	if(sqlite3_exec(db, sqlstr, login_callback, (void*)&connectfd, &errmsg) != SQLITE_OK) {
		printf("error : %s\n", errmsg);
		err_log("errmsg");
	}
	
	strncpy(user_info->data, "OK", 3);

	if(send(connectfd, &user_info, sizeof(USER_INFO), 0) < 0) {
		err_log("Failed to send");
	}

	return;
}

int querry_callback(void *arg, int f_num, char **f_value, char **f_name)
{
	int connectfd;
	USER_INFO user_info;
	connectfd = *(int *)arg;
	printf("after callback %d\n",connectfd);
	sprintf(user_info.data, "%s : %s : %s : %s : %s : %s : %s", f_value[0], f_value[1], f_value[2], f_value[4], f_value[5], f_value[6], f_value[7]);  // 
	//sprintf(user_info.data, "%s", f_value[0]);

//	strncpy(user_info.data, "info from server",16);
	user_info.data[strlen(user_info.data)] = '\0';
//	printf("get user info: %s\n", user_info.data);
	
	send(connectfd, &user_info, sizeof(user_info), 0);
	return 0;
}

void do_querry(int connectfd, USER_INFO *user_info, sqlite3 *db)
{
	char *errmsg;
	char sqlstr[256] = {0};	
	
	sprintf(sqlstr, "select * from user_info where name = '%s'", user_info->name);
		
	if(sqlite3_exec(db, sqlstr, querry_callback, (void *)&connectfd, &errmsg) != SQLITE_OK)
	{
		printf("error : %s\n", errmsg);
		err_log("errmsg");
	}
		
	strncpy(user_info->data, "querry ok",9);
	send(connectfd, user_info, sizeof(USER_INFO), 0);
	
	return ;
}


int querry_callback_xxdk(void *arg, int f_num, char ** f_value, char ** f_name)
{
	int i = 0;
	USER_INFO *user_info = (USER_INFO*)arg;

	err_log("208");	
	for(i = 0; i < f_num; i++)
	{
	//	printf("%-8s %s", f_value[i], f_name[i]);
		printf("%-8s", f_value[i]);
	}

	user_info->root = atoi(f_value[0]);
	err_log("225");	
//	user_info->type = atoi(f_value[1]);
	err_log("225");	
	strcpy(user_info->name, f_value[1]);
	err_log("225");	
	strcpy(user_info->password, f_value[2]);
	err_log("225");	
	strcpy(user_info->addr, f_value[3]);
	err_log("225");	
	user_info->age = atoi(f_value[4]);
	err_log("225");	
	user_info->level = atoi(f_value[5]);
	err_log("225");	
	user_info->no = atoi(f_value[6]);
	err_log("225");	
	strcpy(user_info->phone, f_value[7]);
	err_log("225");	
	user_info->salary = atof(f_value[8]);
//	err_log("226");	
//	strcpy(user_info->data, f_value[10]);
//	err_log("225");
//
	printf("root: %d, name: %s, password: %s\n", 
			user_info->root, user_info->name, user_info->password);

	return 0;
}

void do_querry_xxdk(int connectfd, USER_INFO *user_info, sqlite3 *db)
{
	char sqlstr[256], *errmsg;
	int found = 0;
	char date[256], word[256];

	err_log("236");	
	sprintf(sqlstr, "select * from user_info where no = %d", user_info->no);
	if(sqlite3_exec(db, sqlstr, querry_callback_xxdk, user_info, &errmsg) != SQLITE_OK)
	{
		err_log(errmsg);
	}
	else
	{
		err_log("245");	
		strcpy(user_info->data, "not found");
	}
	err_log("248");
	
	printf("root: %d, name: %s, password: %s\n", 
			user_info->root, user_info->name, user_info->password);
	send(connectfd, user_info, sizeof(USER_INFO), 0);
	err_log("250");	

	return;
}
/***************************************************************************
 * 功能：
 *      数据库为数据库添加成员
 * 参数：
 *      @db_name: 数据库名称
 *      @db     : 记录打开的数据库句柄                                                                                                         
 * 返回值： 
 *      成功 0 ， 失败 -1 
 ***************************************************************************/
void do_add(int connectfd, USER_INFO *user_info, sqlite3 *db)
{
    char sqlstr[256] = {0};
    char *errmsg;
	
	err_log("enter do_add");
//   insert into usr values(id integer primary key autoincrement,root integer,name char,password char,addr char,\
//      age char,level integer,no integer,phone char,salary char);
    sprintf(sqlstr, "insert into user_info values(%d,'%s','%s','%s',%d,%d,%d,'%s',%lf)",user_info->root,user_info->name,\
        user_info->password,user_info->addr,user_info->age,user_info->level,user_info->no,user_info->phone, user_info->salary);

    if(sqlite3_exec(db, sqlstr, NULL, NULL, &errmsg) != SQLITE_OK)
    {
        sprintf(user_info->data, "user:%s, no:%d already exist!!!", user_info->name, user_info->no);
    }
    else
    {
        strncpy(user_info->data, "OK", 3);
    }

    send(connectfd, user_info, sizeof(user_info), 0);
	
	return ;
}

void do_modify(int connectfd, USER_INFO *user_info, sqlite3*db)                                                                               
{
    char sqlstr[256], *errmsg;
	int nrow, ncolumn;
	char **result;

	do_querry_xxdk(connectfd, user_info, db);
	recv(connectfd, user_info, sizeof(USER_INFO), 0);	
	printf("enter modify ,user_info_root:%d\n",user_info->root);
	printf("no:%d, password:%s, phone:%s, level:%d\n",user_info->no,user_info->password,user_info->phone,user_info->level);

#if 1
    if(user_info->root != 1){
        printf("not root\n");
		
       sprintf(sqlstr, "update user_info set password='%s',phone='%s', level=%d where no=%d", user_info->password,user_info->phone, user_info->level, user_info->no);
        if(sqlite3_exec(db, sqlstr, NULL, NULL, &errmsg) != SQLITE_OK)
        {
            err_log(errmsg);
        }   
    
        strcpy(user_info->data, "OK\n");

        send(connectfd, user_info, sizeof(USER_INFO), 0);
        send(connectfd, user_info, sizeof(USER_INFO), 0);
		err_log("update ok");

    }
#endif
    if(user_info->root ==1){
        printf("root\n");                                                                                                             

         sprintf(sqlstr, "update user_info set password='%s',addr='%s',age=%c,level=%d,no=%d,phone='%s',salary=%lf where no =%d)",\
            user_info->password,user_info->addr,user_info->age,user_info->level,user_info->no,user_info->phone,\
            user_info->salary, user_info->no);
        if(sqlite3_exec(db, sqlstr, NULL, NULL, &errmsg) != SQLITE_OK)
        {
            err_log(errmsg);
        }

        strcpy(user_info->data, "OK\n");

        send(connectfd, user_info, sizeof(USER_INFO), 0);

    }

    return;
}


void do_client(int connectfd, sqlite3 *db)
{

	USER_INFO user_info;

	while (recv(connectfd, &user_info, sizeof(USER_INFO), 0) > 0)  // receive request
	{
		printf("type = %d\n", user_info.type);
		printf("name = %s\n", user_info.name);
		printf("password = %s\n", user_info.password);

		switch ( user_info.type )
		{
		case R :
			do_register(connectfd, &user_info, db);
			break;
		case L :
			do_login(connectfd, &user_info, db);
			break;
		case Q :
			do_querry(connectfd, &user_info, db);
			break;
		case A :
			do_add(connectfd, &user_info, db);
			break;
		case M :
			printf("start do modify\n");
			do_modify(connectfd, &user_info, db);
			break;		
		case D :
			do_delete(connectfd, &user_info, db);
			break;
		}
	}
	printf("client quit\n");
	exit(0);
	return;
}

int do_delete(int connectfd, USER_INFO *user_info, sqlite3 *db)
{
	char *errmsg;
	char sqlstr[256] = {0};		

	sprintf(sqlstr, "delete from user_info where no = %d", user_info->no);
		
	if(sqlite3_exec(db, sqlstr, NULL, NULL, &errmsg) != SQLITE_OK)
		{
			printf("error : %s\n", errmsg);
			err_log("errmsg");
		}
		
	user_info->data[0] = '\0';

	send(connectfd, user_info, sizeof(USER_INFO), 0);

	return 0;
}
